using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Linq;
using TVT.DataAccess.Repositories;
using System.Web.Security;
using System.Transactions;
using TVT.Common.Exceptions;
using TVT.Common.Helpers;
using TVT.BizLayer.Managers;
using MathLib;

namespace TVT.BizLayer.Entities
{
    [Serializable]
    public class User:BaseEntity<User>
    {
        #region attribute

        private Guid userId;

        private string firstName;
        private string lastName;
        private string im;
        private string phone1;
        private string email;
        private List<UserAlias> alias = null;
        private string userName;
	    private UserProfile userProfile;
        private decimal match;
        private List<Comment> comments;
        private List<UserRelation> userRelations;
       
        private static DBRepository repository = DBRepository.GetInstance();

        #endregion
        
        #region properties

        public Guid UserId
        {
            get { return userId; }
            set { userId = value; }
        }

        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }

        public string Im
        {
            get { return im; }
            set { im = value; }
        }

        public string Phone1
        {
            get { return phone1; }
            set { phone1 = value; }
        }

        public string Email
        {
            get { return email; }
            set { email = value; }
        }

        public List<UserAlias> Alias
        {
            get 
            {
                if (alias == null)
                {
                    alias = UserAlias.FindAllByUser(this.UserId);
                }
                return alias;
            }
            set {
                this.alias = value;
            }

        }

        public string UserName
        {
            get { return userName; }
            set { userName = value; }
        }

        public UserProfile UserProfile
        {
            get
            {
                if (this.userProfile == null)
                    userProfile = UserProfile.Find(this.userId);
                return userProfile;
            }
            set { userProfile = value; }
        }

        public decimal Match
        {
            get { return match; }
            set { match = value; }
        }

        public int Age
        {
            get 
            {
                int years = DateTime.Today.Year - this.UserProfile.BirthDate.Year;  
                if(DateTime.Today < this.UserProfile.BirthDate)
                    years--;
                return years;
            }
        }

        public List<Comment> Comments
        {
            get
            {
                if (this.comments == null)
                    comments = Comment.FindCommentsToUser(this.UserId);
                return comments;
            }
        }


        public List<UserRelation> UserRelations
        {
            get
            {
                if (this.userRelations == null)
                    userRelations = UserRelation.FindAll(this.UserId, TVT.Common.Helpers.Enumerators.RelationStatus.DontCare);
                return userRelations;
            }
        }

        #endregion

        #region Methods

        public override void Insert()
        {
            throw new NotImplementedException();
        }

        public override void Delete()
        {
            Delete(this.userId);
        }

        public override void Save()
        {
            repository.SaveUser(this.userId, this.firstName, this.lastName, this.im, this.phone1);
            foreach (var item in this.Alias)
            {
                item.IdUser = this.userId;
                item.Save();
            }
            if(this.userProfile != null)
            {
                this.userProfile.UserId = this.userId;
                this.userProfile.Save();
            }
            
        }

        public override void Update()
        {
            repository.UpdateUser(this.userId, this.firstName, this.lastName, this.im, this.phone1);
            
        }

        public static List<User> FindAll()
        {
            List<User> users = MapToEntities(repository.FindAllUsers());                        
            return users;
        }

        public IEnumerable<User> FindMatchs()
        {
            List<User> users = MapToEntities(repository.FindMatchs(this.UserId));
            foreach (User user in users)
            {
                Vector myDiffVector = this.UserProfile.EigenFaceVector;
                Vector userDiffVector = user.UserProfile.EigenFaceVector;

                double result = (myDiffVector - userDiffVector).Abs();

                result *= 30;
                result = 100 - result;
                if(result < 0 ) result = 0;
                if(result > 100 ) result = 100;
                user.Match = (decimal)(result);
            }

            IEnumerable<User> sorted = from u in users
                                       orderby u.Match descending
                                       select u;
            return sorted;
        }

        public static User Find(Guid userId)
        {
            User user = MapToEntity(repository.FindUser(userId));
            return user;
        }

        public static bool Delete(Guid userId)
        {
            using (TransactionScope tran = new TransactionScope())
            {
                try
                {
                    MembershipUser membershipUser = Membership.GetUser(userId);

                    string[] roles = Roles.GetRolesForUser(membershipUser.UserName);
                    Roles.RemoveUserFromRoles(membershipUser.UserName, roles);
                    
                    if (Membership.DeleteUser(membershipUser.UserName))
                    {
                        repository.DeleteAllUserAliasByIdUser(userId);
                        repository.DeleteUser(userId);                        
                        tran.Complete();
                    }
                    else
                    {
                        throw new FunctionalException("Could not delete membership user.");
                    }
                }
                catch (FunctionalException ex)
                {
                    tran.Dispose();
                    throw ex;
                }
                catch (Exception ex)
                {
                    tran.Dispose();
                    throw ex;
                }
            }
            return true;
        }

        public static User FindByPlatformAlias(Enumerators.Platform platform, string name)
        {
            return MapToEntity(repository.FindUserByAliasPlatformAndName((int)platform, name));
        }

        #endregion

    }
}
